//+------------------------------------------------------------------+
//|                                               TradeOrchestrator.mqh |
//|                                    Copyright 2024, Precision EA  |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, Precision EA"
#property strict

#include "Logger.mqh"
#include "TimeManager.mqh"
#include "GoldSignalGenerator.mqh"
#include "RiskManager.mqh"
#include "ExecutionEngine.mqh"

class TradeOrchestrator {
private:
    // Modules
    TimeManager *m_time_manager;
    GoldSignalGenerator *m_signal_generator;
    RiskManager *m_risk_manager;
    ExecutionEngine *m_execution_engine;
    
    // Configuration
    string m_symbol;
    bool m_auto_trading;
    bool m_enable_logging;
    int m_signal_check_interval;
    datetime m_last_signal_check;
    datetime m_last_status_update;
    
    // Statistics
    struct Stats {
        int signals_generated;
        int signals_executed;
        int signals_rejected;
        double total_profit;
        double total_loss;
        int win_count;
        int loss_count;
        datetime start_time;
    } m_stats;
    
    // State
    bool m_initialized;
    bool m_running;
    bool m_emergency_stop;
    
    void InitializeStats() {
        m_stats.signals_generated = 0;
        m_stats.signals_executed = 0;
        m_stats.signals_rejected = 0;
        m_stats.total_profit = 0;
        m_stats.total_loss = 0;
        m_stats.win_count = 0;
        m_stats.loss_count = 0;
        m_stats.start_time = TimeCurrent();
    }
    
    bool InitializeModules() {
        Logger::Info("Initializing modules...", "Orchestrator");
        
        // Initialize Time Manager
        m_time_manager = new TimeManager();
        if(m_time_manager == NULL) {
            Logger::Critical("Failed to create TimeManager", "Orchestrator");
            return false;
        }
        
        // Initialize Signal Generator
        m_signal_generator = new GoldSignalGenerator(m_symbol);
        if(m_signal_generator == NULL) {
            Logger::Critical("Failed to create SignalGenerator", "Orchestrator");
            return false;
        }
        
        // Initialize Risk Manager
        m_risk_manager = new RiskManager(m_symbol);
        if(m_risk_manager == NULL) {
            Logger::Critical("Failed to create RiskManager", "Orchestrator");
            return false;
        }
        
        // Initialize Execution Engine
        m_execution_engine = new ExecutionEngine(m_symbol);
        if(m_execution_engine == NULL) {
            Logger::Critical("Failed to create ExecutionEngine", "Orchestrator");
            return false;
        }
        
        Logger::Info("All modules initialized successfully", "Orchestrator");
        return true;
    }
    
    void CleanupModules() {
        if(m_time_manager != NULL) {
            delete m_time_manager;
            m_time_manager = NULL;
        }
        
        if(m_signal_generator != NULL) {
            delete m_signal_generator;
            m_signal_generator = NULL;
        }
        
        if(m_risk_manager != NULL) {
            delete m_risk_manager;
            m_risk_manager = NULL;
        }
        
        if(m_execution_engine != NULL) {
            delete m_execution_engine;
            m_execution_engine = NULL;
        }
        
        Logger::Info("Modules cleaned up", "Orchestrator");
    }
    
    void ProcessSignal() {
        if(!m_auto_trading || m_emergency_stop) {
            return;
        }
        
        // Generate signal
        GoldSignalGenerator::Signal signal = m_signal_generator->GenerateSignal();
        m_stats.signals_generated++;
        
        if(!signal.valid) {
            Logger::Debug("Invalid signal: " + signal.reason, "Orchestrator");
            m_stats.signals_rejected++;
            return;
        }
        
        // Assess risk
        RiskManager::RiskAssessment risk = m_risk_manager->AssessTrade(
            signal.entry_price,
            signal.stop_loss,
            signal.take_profit,
            signal.confidence
        );
        
        if(!risk.allowed) {
            Logger::Info("Signal rejected by risk manager: " + risk.reason, "Orchestrator");
            m_stats.signals_rejected++;
            return;
        }
        
        // Execute trade
        ExecutionResult result = m_execution_engine->ExecuteOrder(
            signal.type,
            risk.position_size,
            signal.entry_price,
            signal.stop_loss,
            signal.take_profit,
            StringFormat("Auto: %.0f%% conf", signal.confidence * 100)
        );
        
        if(result.status == EXECUTION_SUCCESS) {
            m_stats.signals_executed++;
            Logger::Info(StringFormat("Trade executed: %d", result.ticket), "Orchestrator");
        } else {
            m_stats.signals_rejected++;
            Logger::Error("Trade execution failed: " + result.error_message, "Orchestrator");
        }
    }
    
    void MonitorPositions() {
        // Check for closed positions and update statistics
        int total = PositionsTotal();
        for(int i = total - 1; i >= 0; i--) {
            ulong ticket = PositionGetTicket(i);
            if(ticket > 0 && PositionGetString(POSITION_SYMBOL) == m_symbol) {
                double profit = PositionGetDouble(POSITION_PROFIT);
                if(profit != 0) { // Position closed
                    m_risk_manager->RecordTradeResult(ticket, profit);
                    
                    if(profit > 0) {
                        m_stats.total_profit += profit;
                        m_stats.win_count++;
                    } else {
                        m_stats.total_loss += profit;
                        m_stats.loss_count++;
                    }
                }
            }
        }
    }
    
    void CheckEmergencyConditions() {
        // Check account drawdown
        double drawdown = m_risk_manager->GetDrawdown();
        if(drawdown > 10.0) { // 10% drawdown limit
            m_emergency_stop = true;
            Logger::Critical(StringFormat("Emergency stop: Drawdown %.1f%%", drawdown), "Orchestrator");
        }
        
        // Check margin level
        double margin_level = AccountInfoDouble(ACCOUNT_MARGIN_LEVEL);
        if(margin_level > 0 && margin_level < 50) { // 50% margin level limit
            m_emergency_stop = true;
            Logger::Critical(StringFormat("Emergency stop: Margin level %.1f%%", margin_level), "Orchestrator");
        }
        
        if(m_emergency_stop) {
            m_execution_engine->CloseAllPositions();
            m_auto_trading = false;
        }
    }

public:
    TradeOrchestrator(string symbol = "") {
        m_symbol = (symbol == "") ? _Symbol : symbol;
        m_auto_trading = true;
        m_enable_logging = true;
        m_signal_check_interval = 60; // 1 minute
        m_initialized = false;
        m_running = false;
        m_emergency_stop = false;
        m_last_signal_check = 0;
        m_last_status_update = 0;
        
        InitializeStats();
        
        Logger::Initialize(m_symbol);
        Logger::Info(StringFormat("Orchestrator created for %s", m_symbol), "Orchestrator");
    }
    
    ~TradeOrchestrator() {
        Stop();
        CleanupModules();
        Logger::Info("Orchestrator destroyed", "Orchestrator");
    }
    
    bool Initialize() {
        if(m_initialized) {
            Logger::Warn("Already initialized", "Orchestrator");
            return true;
        }
        
        if(!InitializeModules()) {
            Logger::Critical("Failed to initialize modules", "Orchestrator");
            return false;
        }
        
        m_initialized = true;
        m_running = true;
        
        Logger::Info("Orchestrator initialized successfully", "Orchestrator");
        return true;
    }
    
    void Start() {
        if(!m_initialized && !Initialize()) {
            return;
        }
        
        m_running = true;
        m_auto_trading = true;
        Logger::Info("Orchestrator started", "Orchestrator");
    }
    
    void Stop() {
        m_running = false;
        m_auto_trading = false;
        Logger::Info("Orchestrator stopped", "Orchestrator");
    }
    
    void Pause() {
        m_auto_trading = false;
        Logger::Info("Orchestrator paused", "Orchestrator");
    }
    
    void Resume() {
        m_auto_trading = true;
        Logger::Info("Orchestrator resumed", "Orchestrator");
    }
    
    void OnTick() {
        if(!m_running || !m_initialized) {
            return;
        }
        
        datetime now = TimeCurrent();
        
        // Check emergency conditions
        CheckEmergencyConditions();
        
        // Monitor positions
        MonitorPositions();
        
        // Generate signals at specified interval
        if(now - m_last_signal_check >= m_signal_check_interval) {
            ProcessSignal();
            m_last_signal_check = now;
        }
        
        // Update status display every 5 minutes
        if(now - m_last_status_update >= 300) {
            PrintStatus();
            m_last_status_update = now;
        }
        
        // Cleanup indicators periodically
        if(m_signal_generator != NULL && now % 3600 == 0) {
            m_signal_generator->Cleanup();
        }
    }
    
    void EmergencyStop() {
        m_emergency_stop = true;
        m_auto_trading = false;
        m_execution_engine->CloseAllPositions();
        Logger::Critical("EMERGENCY STOP ACTIVATED", "Orchestrator");
    }
    
    void ResetEmergency() {
        m_emergency_stop = false;
        Logger::Info("Emergency reset", "Orchestrator");
    }
    
    string GetStatus() const {
        string status = "=== TRADE ORCHESTRATOR ===\n";
        status += StringFormat("Symbol: %s\n", m_symbol);
        status += StringFormat("Status: %s\n", m_running ? "RUNNING" : "STOPPED");
        status += StringFormat("Auto Trading: %s\n", m_auto_trading ? "ON" : "OFF");
        status += StringFormat("Emergency Stop: %s\n", m_emergency_stop ? "ACTIVE" : "INACTIVE");
        status += StringFormat("Uptime: %s\n", TimeToString(TimeCurrent() - m_stats.start_time, TIME_SECONDS));
        status += "\n=== STATISTICS ===\n";
        status += StringFormat("Signals: %d generated, %d executed, %d rejected\n", 
            m_stats.signals_generated, m_stats.signals_executed, m_stats.signals_rejected);
        status += StringFormat("Trades: %d wins, %d losses\n", m_stats.win_count, m_stats.loss_count);
        status += StringFormat("P&L: $%.2f (Profit: $%.2f, Loss: $%.2f)\n", 
            m_stats.total_profit + m_stats.total_loss, 
            m_stats.total_profit, m_stats.total_loss);
        status += StringFormat("Win Rate: %.1f%%\n", 
            m_stats.win_count + m_stats.loss_count > 0 ? 
            (double)m_stats.win_count / (m_stats.win_count + m_stats.loss_count) * 100 : 0);
        
        if(m_risk_manager != NULL) {
            status += "\n" + m_risk_manager->GetStatus();
        }
        
        if(m_time_manager != NULL) {
            status += "\n" + m_time_manager->GetCurrentTimeInfo();
        }
        
        return status;
    }
    
    void PrintStatus() const {
        Print(GetStatus());
    }
    
    GoldSignalGenerator* GetSignalGenerator() const { return m_signal_generator; }
    RiskManager* GetRiskManager() const { return m_risk_manager; }
    ExecutionEngine* GetExecutionEngine() const { return m_execution_engine; }
    bool IsRunning() const { return m_running && !m_emergency_stop; }
    bool IsAutoTrading() const { return m_auto_trading; }
};